const fs = require('fs');
const path = require('path');

/**
 * OpenHarmony 全面统计与学习系统
 * 目标：
 * 1. 统计所有代码仓和子系统
 * 2. 分析代码特征（文件类型、代码量、复杂度）
 * 3. 学习架构模式（bundle.json、innerkits、GN层级）
 * 4. 提取测试模式（unittest、fuzztest）
 * 5. 构建知识图谱
 */
class ComprehensiveOHLearner {
    constructor(ohcodeDir) {
        this.ohcodeDir = ohcodeDir;
        this.statistics = {
            // 基础统计
            totalRepos: 0,
            totalSubsystems: new Set(),
            totalComponents: 0,
            
            // 代码统计
            fileStats: {
                cpp: 0,
                h: 0,
                gn: 0,
                json: 0,
                test_cpp: 0,
                fuzzer_cpp: 0
            },
            
            // 代码行数
            linesOfCode: {
                source: 0,
                header: 0,
                test: 0,
                fuzz: 0,
                gn: 0
            },
            
            // 函数统计
            functions: {
                total: 0,
                ndk_interfaces: 0,  // OH_ 开头
                public_methods: 0,
                test_cases: 0,      // HWTEST_F
                fuzzer_functions: 0
            },
            
            // 架构统计
            architecture: {
                components: [],
                innerkits: [],
                dependencies: {},
                gnHierarchy: {}
            },
            
            // 测试统计
            testCoverage: {
                totalSourceFiles: 0,
                filesWithTests: 0,
                filesWithFuzz: 0,
                testFileRatio: 0,
                fuzzFileRatio: 0
            },
            
            // 仓库详情
            repositories: []
        };
    }

    /**
     * 主统计流程
     */
    async run() {
        console.log('🚀 开始全面统计与学习 OpenHarmony 代码库...\n');
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
        
        const startTime = Date.now();
        
        // 步骤1：扫描所有仓库
        await this.scanAllRepositories();
        
        // 步骤2：统计代码特征
        await this.analyzeCodeCharacteristics();
        
        // 步骤3：学习架构模式
        await this.learnArchitecturePatterns();
        
        // 步骤4：分析测试覆盖
        await this.analyzeTestCoverage();
        
        // 步骤5：提取代码模式
        await this.extractCodePatterns();
        
        // 步骤6：构建依赖图谱
        await this.buildDependencyGraph();
        
        // 步骤7：保存结果
        await this.saveResults();
        
        const duration = ((Date.now() - startTime) / 1000).toFixed(2);
        
        console.log(`\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
        console.log(`✅ 统计完成！耗时: ${duration} 秒`);
        
        this.printComprehensiveSummary();
    }

    /**
     * 步骤1：扫描所有仓库
     */
    async scanAllRepositories() {
        console.log('📦 步骤1: 扫描所有代码仓库...\n');
        
        const topLevelDirs = ['arkcompiler', 'base', 'build', 'commonlibrary', 
                              'device', 'drivers', 'foundation'];
        
        for (const dir of topLevelDirs) {
            const dirPath = path.join(this.ohcodeDir, dir);
            if (!fs.existsSync(dirPath)) continue;
            
            await this.scanDirectory(dirPath, dir);
        }
        
        console.log(`   ✅ 扫描完成: ${this.statistics.totalRepos} 个代码仓\n`);
    }

    /**
     * 递归扫描目录，识别代码仓（包含 bundle.json 的目录）
     */
    async scanDirectory(dirPath, subsystem) {
        const entries = fs.readdirSync(dirPath, { withFileTypes: true });
        
        // 检查当前目录是否是一个代码仓（包含 bundle.json）
        const hasBundleJson = entries.some(e => e.name === 'bundle.json');
        
        if (hasBundleJson) {
            this.statistics.totalRepos++;
            const repoName = path.basename(dirPath);
            console.log(`   [${this.statistics.totalRepos}] ${subsystem}/${repoName}`);
            
            const repoInfo = await this.analyzeRepository(dirPath, subsystem);
            this.statistics.repositories.push(repoInfo);
            return; // 找到仓库，不再向下递归
        }
        
        // 继续向下查找
        for (const entry of entries) {
            if (entry.isDirectory() && !entry.name.startsWith('.')) {
                const subPath = path.join(dirPath, entry.name);
                await this.scanDirectory(subPath, subsystem);
            }
        }
    }

    /**
     * 分析单个代码仓
     */
    async analyzeRepository(repoPath, subsystem) {
        const repoName = path.basename(repoPath);
        
        // 解析 bundle.json
        const bundlePath = path.join(repoPath, 'bundle.json');
        let bundle = null;
        try {
            bundle = JSON.parse(fs.readFileSync(bundlePath, 'utf-8'));
        } catch (e) {
            console.log(`      ⚠️ 无法解析 bundle.json: ${e.message}`);
        }
        
        // 统计文件
        const files = this.scanFilesRecursive(repoPath);
        
        return {
            name: repoName,
            path: repoPath,
            subsystem,
            component: bundle?.name || repoName,
            bundle,
            files
        };
    }

    /**
     * 递归扫描文件
     */
    scanFilesRecursive(dir, result = {}) {
        if (!fs.existsSync(dir)) return result;
        
        try {
            const entries = fs.readdirSync(dir, { withFileTypes: true });
            
            for (const entry of entries) {
                const fullPath = path.join(dir, entry.name);
                
                if (entry.isDirectory()) {
                    // 跳过常见的非代码目录
                    if (['node_modules', '.git', 'build', 'out', 'dist'].includes(entry.name)) {
                        continue;
                    }
                    this.scanFilesRecursive(fullPath, result);
                } else if (entry.isFile()) {
                    const ext = path.extname(entry.name);
                    const category = this.categorizeFile(entry.name, fullPath);
                    
                    if (!result[category]) {
                        result[category] = [];
                    }
                    result[category].push(fullPath);
                }
            }
        } catch (e) {
            // 权限错误等，跳过
        }
        
        return result;
    }

    /**
     * 文件分类
     */
    categorizeFile(fileName, fullPath) {
        if (fileName.endsWith('_test.cpp') || fileName.endsWith('_unittest.cpp')) {
            return 'test_cpp';
        }
        if (fileName.endsWith('_fuzzer.cpp') || fullPath.includes('/fuzztest/')) {
            return 'fuzzer_cpp';
        }
        if (fileName.endsWith('.cpp') || fileName.endsWith('.cc')) {
            return 'cpp';
        }
        if (fileName.endsWith('.h') || fileName.endsWith('.hpp')) {
            return 'h';
        }
        if (fileName === 'BUILD.gn' || fileName.endsWith('.gn')) {
            return 'gn';
        }
        if (fileName === 'bundle.json' || fileName.endsWith('.json')) {
            return 'json';
        }
        return 'other';
    }

    /**
     * 步骤2：统计代码特征
     */
    async analyzeCodeCharacteristics() {
        console.log('\n📊 步骤2: 分析代码特征...\n');
        
        for (const repo of this.statistics.repositories) {
            // 统计文件数量
            for (const [category, files] of Object.entries(repo.files)) {
                if (this.statistics.fileStats[category] !== undefined) {
                    this.statistics.fileStats[category] += files.length;
                }
            }
            
            // 统计代码行数和函数
            await this.countLinesAndFunctions(repo);
        }
        
        console.log('   ✅ 代码特征分析完成\n');
    }

    /**
     * 统计代码行数和函数数量
     */
    async countLinesAndFunctions(repo) {
        // 统计源文件
        if (repo.files.cpp) {
            for (const file of repo.files.cpp) {
                const content = this.safeReadFile(file);
                if (content) {
                    const lines = content.split('\n').length;
                    this.statistics.linesOfCode.source += lines;
                    
                    // 统计函数
                    const functions = this.extractFunctions(content);
                    this.statistics.functions.total += functions.length;
                    this.statistics.functions.ndk_interfaces += 
                        functions.filter(f => f.startsWith('OH_')).length;
                }
            }
        }
        
        // 统计头文件
        if (repo.files.h) {
            for (const file of repo.files.h) {
                const content = this.safeReadFile(file);
                if (content) {
                    const lines = content.split('\n').length;
                    this.statistics.linesOfCode.header += lines;
                }
            }
        }
        
        // 统计测试文件
        if (repo.files.test_cpp) {
            for (const file of repo.files.test_cpp) {
                const content = this.safeReadFile(file);
                if (content) {
                    const lines = content.split('\n').length;
                    this.statistics.linesOfCode.test += lines;
                    
                    // 统计测试用例
                    const testCases = (content.match(/HWTEST_F/g) || []).length;
                    this.statistics.functions.test_cases += testCases;
                }
            }
        }
        
        // 统计 Fuzz 文件
        if (repo.files.fuzzer_cpp) {
            for (const file of repo.files.fuzzer_cpp) {
                const content = this.safeReadFile(file);
                if (content) {
                    const lines = content.split('\n').length;
                    this.statistics.linesOfCode.fuzz += lines;
                    this.statistics.functions.fuzzer_functions++;
                }
            }
        }
    }

    /**
     * 提取函数名
     */
    extractFunctions(code) {
        const functions = [];
        const funcRegex = /(?:^|\n)\s*(?:\w+\s+)+(\w+)\s*\(/gm;
        let match;
        while ((match = funcRegex.exec(code)) !== null) {
            functions.push(match[1]);
        }
        return functions;
    }

    /**
     * 安全读取文件
     */
    safeReadFile(filePath) {
        try {
            return fs.readFileSync(filePath, 'utf-8');
        } catch (e) {
            return null;
        }
    }

    /**
     * 步骤3：学习架构模式
     */
    async learnArchitecturePatterns() {
        console.log('\n🏗️  步骤3: 学习架构模式...\n');
        
        for (const repo of this.statistics.repositories) {
            if (repo.bundle) {
                // 记录部件信息
                this.statistics.architecture.components.push({
                    name: repo.bundle.name,
                    subsystem: repo.bundle.component?.subsystem,
                    innerKits: repo.bundle.component?.innerKits || []
                });
                
                this.statistics.totalSubsystems.add(repo.bundle.component?.subsystem);
                this.statistics.totalComponents++;
                
                // 学习 innerkits
                const innerkitsDir = path.join(repo.path, 'interfaces/inner_kits');
                if (fs.existsSync(innerkitsDir)) {
                    const headers = this.findHeaders(innerkitsDir);
                    this.statistics.architecture.innerkits.push({
                        component: repo.bundle.name,
                        headers: headers.map(h => path.relative(repo.path, h))
                    });
                }
            }
        }
        
        console.log(`   ✅ 发现 ${this.statistics.totalComponents} 个部件\n`);
        console.log(`   ✅ 发现 ${this.statistics.totalSubsystems.size} 个子系统\n`);
    }

    /**
     * 查找头文件
     */
    findHeaders(dir) {
        const headers = [];
        try {
            const entries = fs.readdirSync(dir, { withFileTypes: true });
            for (const entry of entries) {
                const fullPath = path.join(dir, entry.name);
                if (entry.isDirectory()) {
                    headers.push(...this.findHeaders(fullPath));
                } else if (entry.name.endsWith('.h')) {
                    headers.push(fullPath);
                }
            }
        } catch (e) {
            // 跳过
        }
        return headers;
    }

    /**
     * 步骤4：分析测试覆盖
     */
    async analyzeTestCoverage() {
        console.log('\n🧪 步骤4: 分析测试覆盖率...\n');
        
        for (const repo of this.statistics.repositories) {
            const sourceCount = (repo.files.cpp || []).length;
            const testCount = (repo.files.test_cpp || []).length;
            const fuzzCount = (repo.files.fuzzer_cpp || []).length;
            
            this.statistics.testCoverage.totalSourceFiles += sourceCount;
            this.statistics.testCoverage.filesWithTests += testCount;
            this.statistics.testCoverage.filesWithFuzz += fuzzCount;
        }
        
        if (this.statistics.testCoverage.totalSourceFiles > 0) {
            this.statistics.testCoverage.testFileRatio = 
                (this.statistics.testCoverage.filesWithTests / 
                 this.statistics.testCoverage.totalSourceFiles * 100).toFixed(2);
            
            this.statistics.testCoverage.fuzzFileRatio = 
                (this.statistics.testCoverage.filesWithFuzz / 
                 this.statistics.testCoverage.totalSourceFiles * 100).toFixed(2);
        }
        
        console.log(`   ✅ 测试文件比例: ${this.statistics.testCoverage.testFileRatio}%\n`);
        console.log(`   ✅ Fuzz 文件比例: ${this.statistics.testCoverage.fuzzFileRatio}%\n`);
    }

    /**
     * 步骤5：提取代码模式
     */
    async extractCodePatterns() {
        console.log('\n📐 步骤5: 提取代码模式...\n');
        
        // 构建头文件 → 部件映射
        const headerToComponent = {};
        for (const innerkit of this.statistics.architecture.innerkits) {
            for (const header of innerkit.headers) {
                const headerName = path.basename(header);
                headerToComponent[headerName] = innerkit.component;
            }
        }
        
        this.statistics.architecture.headerToComponent = headerToComponent;
        
        console.log(`   ✅ 建立 ${Object.keys(headerToComponent).length} 个头文件映射\n`);
    }

    /**
     * 步骤6：构建依赖图谱
     */
    async buildDependencyGraph() {
        console.log('\n🔗 步骤6: 构建依赖图谱...\n');
        
        // 分析所有 BUILD.gn 文件中的 external_deps
        for (const repo of this.statistics.repositories) {
            if (repo.files.gn) {
                for (const gnFile of repo.files.gn) {
                    const content = this.safeReadFile(gnFile);
                    if (content) {
                        const externalDeps = this.extractExternalDeps(content);
                        for (const dep of externalDeps) {
                            if (!this.statistics.architecture.dependencies[dep]) {
                                this.statistics.architecture.dependencies[dep] = [];
                            }
                            this.statistics.architecture.dependencies[dep].push(repo.component);
                        }
                    }
                }
            }
        }
        
        console.log(`   ✅ 发现 ${Object.keys(this.statistics.architecture.dependencies).length} 个依赖关系\n`);
    }

    /**
     * 提取 external_deps
     */
    extractExternalDeps(gnContent) {
        const deps = [];
        const regex = /external_deps\s*=\s*\[([\s\S]*?)\]/g;
        let match;
        while ((match = regex.exec(gnContent)) !== null) {
            const depsStr = match[1];
            const depItems = depsStr.match(/"([^"]+)"/g);
            if (depItems) {
                deps.push(...depItems.map(d => d.replace(/"/g, '')));
            }
        }
        return [...new Set(deps)];
    }

    /**
     * 步骤7：保存结果
     */
    async saveResults() {
        // 保存详细统计
        const statsPath = path.join(__dirname, '../core/knowledge/openharmony-statistics.json');
        fs.writeFileSync(statsPath, JSON.stringify(this.statistics, null, 2), 'utf-8');
        
        // 保存简化的架构信息（用于推理引擎）
        const archPath = path.join(__dirname, '../core/knowledge/openharmony-architecture.json');
        fs.writeFileSync(archPath, JSON.stringify({
            components: this.statistics.architecture.components,
            headerToComponent: this.statistics.architecture.headerToComponent,
            dependencies: this.statistics.architecture.dependencies,
            innerkits: this.statistics.architecture.innerkits
        }, null, 2), 'utf-8');
        
        console.log(`\n💾 结果已保存:`);
        console.log(`   - ${statsPath}`);
        console.log(`   - ${archPath}`);
    }

    /**
     * 打印综合摘要
     */
    printComprehensiveSummary() {
        console.log('\n📊 ═══════════════════════════════════════════════════════');
        console.log('                    综合统计摘要');
        console.log('═══════════════════════════════════════════════════════\n');
        
        console.log('【仓库与架构】');
        console.log(`  • 代码仓总数:          ${this.statistics.totalRepos.toLocaleString()}`);
        console.log(`  • 子系统数量:          ${this.statistics.totalSubsystems.size}`);
        console.log(`  • 部件总数:            ${this.statistics.totalComponents}`);
        console.log(`  • innerkits 导出:      ${this.statistics.architecture.innerkits.length}`);
        console.log(`  • 跨仓依赖:            ${Object.keys(this.statistics.architecture.dependencies).length}\n`);
        
        console.log('【代码规模】');
        console.log(`  • C++ 源文件:          ${this.statistics.fileStats.cpp.toLocaleString()}`);
        console.log(`  • 头文件:              ${this.statistics.fileStats.h.toLocaleString()}`);
        console.log(`  • BUILD.gn:            ${this.statistics.fileStats.gn.toLocaleString()}`);
        console.log(`  • 测试文件:            ${this.statistics.fileStats.test_cpp.toLocaleString()}`);
        console.log(`  • Fuzzer 文件:         ${this.statistics.fileStats.fuzzer_cpp.toLocaleString()}\n`);
        
        console.log('【代码行数】');
        console.log(`  • 源代码:              ${this.statistics.linesOfCode.source.toLocaleString()} 行`);
        console.log(`  • 头文件:              ${this.statistics.linesOfCode.header.toLocaleString()} 行`);
        console.log(`  • 测试代码:            ${this.statistics.linesOfCode.test.toLocaleString()} 行`);
        console.log(`  • Fuzz 代码:           ${this.statistics.linesOfCode.fuzz.toLocaleString()} 行`);
        console.log(`  • 总计:                ${(this.statistics.linesOfCode.source + 
                                                this.statistics.linesOfCode.header + 
                                                this.statistics.linesOfCode.test + 
                                                this.statistics.linesOfCode.fuzz).toLocaleString()} 行\n`);
        
        console.log('【函数统计】');
        console.log(`  • 函数总数:            ${this.statistics.functions.total.toLocaleString()}`);
        console.log(`  • NDK 接口 (OH_*):     ${this.statistics.functions.ndk_interfaces.toLocaleString()}`);
        console.log(`  • 测试用例 (HWTEST_F): ${this.statistics.functions.test_cases.toLocaleString()}`);
        console.log(`  • Fuzzer 函数:         ${this.statistics.functions.fuzzer_functions.toLocaleString()}\n`);
        
        console.log('【测试覆盖】');
        console.log(`  • 源文件总数:          ${this.statistics.testCoverage.totalSourceFiles.toLocaleString()}`);
        console.log(`  • 有测试的文件:        ${this.statistics.testCoverage.filesWithTests.toLocaleString()} (${this.statistics.testCoverage.testFileRatio}%)`);
        console.log(`  • 有 Fuzz 的文件:      ${this.statistics.testCoverage.filesWithFuzz.toLocaleString()} (${this.statistics.testCoverage.fuzzFileRatio}%)`);
        
        console.log('\n═══════════════════════════════════════════════════════\n');
    }
}

// 运行
const learner = new ComprehensiveOHLearner('./OHCode');
learner.run().then(() => {
    console.log('🎉 全面统计与学习完成！\n');
    process.exit(0);
}).catch(err => {
    console.error('❌ 错误:', err);
    process.exit(1);
});

